package com.ruoyi.web.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.web.common.ProjectConstant;
import com.ruoyi.web.dto.AddTallyReq;
import com.ruoyi.web.entity.BalanceChangeDetail;
import com.ruoyi.web.entity.UserBalance;
import com.ruoyi.web.mapper.BalanceChangeDetailMapper;
import com.ruoyi.web.mapper.UserBalanceMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * <br>
 *
 * @author chenwujie
 * @date 2021/2/11
 */
@Service
public class UserBalanceService extends ServiceImpl<UserBalanceMapper, UserBalance> {
    @Resource
    private BalanceChangeDetailMapper balanceChangeDetailMapper;
    @Resource
    private AccountInfoService accountInfoService;

    /**
     * 动账业务，存入或取出钱 <br>
     *
     * @param
     * @param addTallyReq
     * @return void
     * @throws
     * @author chenwujie
     * @since 2021/2/11
     */
    @Transactional(rollbackFor = Throwable.class)
    public void balanceBusiness(AddTallyReq addTallyReq) {
        LocalDateTime now = LocalDateTime.now();

        String userName = addTallyReq.getUserName();

        /*查询用户余额*/
        UserBalance userBalance = selectByUser(userName, now);
        if (userBalance == null) {
            /*没有用户，就初始化一个*/
            userBalance = new UserBalance();
//            userBalance.setId();
            userBalance.setUserName(userName);
            userBalance.setBalance(BigDecimal.ZERO);
            userBalance.setStartDate(now);
            userBalance.setEndDate(ProjectConstant.FOREVER_DATE_TIME);
            this.save(userBalance);
        }
        BigDecimal amount = new BigDecimal(addTallyReq.getAmount());

        BalanceChangeDetail balanceChangeDetail = new BalanceChangeDetail();
        balanceChangeDetail.setUserName(userName);
        balanceChangeDetail.setAmount(amount);
        balanceChangeDetail.setTranType(addTallyReq.getTranType());
        balanceChangeDetail.setCreateTime(now);
        balanceChangeDetail.setRemark(addTallyReq.getRemark());
        if (addTallyReq.getImageFile() != null) {
            balanceChangeDetail.setImageFile(addTallyReq.getImageFile().getBytes());
        }

        /*今天第一次更新余额，重新设定余额的日期范围*/
        userBalance.setEndDate(now);

        UserBalance newUserBalance = new UserBalance();
        newUserBalance.setUserName(userBalance.getUserName());
        newUserBalance.setBalance(userBalance.getBalance());
        newUserBalance.setStartDate(now);
        newUserBalance.setEndDate(ProjectConstant.FOREVER_DATE_TIME);

        calc(newUserBalance, balanceChangeDetail);

        this.saveOrUpdate(userBalance);
        this.saveOrUpdate(newUserBalance);

        balanceChangeDetailMapper.insert(balanceChangeDetail);


        // 更新流动资金
        if ("存入".equals(balanceChangeDetail.getTranType())) {
            accountInfoService.updateAccountAdd(amount);
        } else {
            accountInfoService.updateAccountSubtract(amount);
        }
    }

    private void calc(UserBalance userBalance, BalanceChangeDetail balanceChangeDetail) {
        if ("存入".equals(balanceChangeDetail.getTranType())) {
            userBalance.setBalance(userBalance.getBalance().add(balanceChangeDetail.getAmount()));
        } else {
            userBalance.setBalance(userBalance.getBalance().subtract(balanceChangeDetail.getAmount()));
//            if (userBalance.getBalance().compareTo(BigDecimal.ZERO) < 0) {
//                throw new BusinessException("余额扣减后小于0，扣减后余额：{0}", userBalance.getBalance());
//            }
        }
    }


    public UserBalance selectByUser(String userName, LocalDateTime dateTime) {
        LambdaQueryWrapper<UserBalance> param = new QueryWrapper<UserBalance>()
                .lambda()
                .eq(UserBalance::getUserName, userName)
                .gt(UserBalance::getEndDate, dateTime)
                .le(UserBalance::getStartDate, dateTime);


        return this.baseMapper.selectOne(param);
    }

}